package com.ushine.web.template.authority.controller;

import com.ushine.web.base.model.system.UserDO;
import com.ushine.web.component.authority.annotation.DataPermissionFilter;
import com.ushine.web.component.authority.config.DataFilterThreadLocal;
import com.ushine.web.component.exception.ServiceException;
import com.ushine.web.component.http.HttpResponseVO;
import com.ushine.web.log.annotation.SystemControllerLog;
import com.ushine.web.log.constant.LogConstant;
import com.ushine.web.security.utils.SecurityUtils;
import com.ushine.web.template.authority.facade.IStaffFacade;
import com.ushine.web.template.authority.mapper.StaffMapper;
import com.ushine.web.template.authority.model.StaffDO;
import com.ushine.web.template.authority.service.IStaffService;
import com.ushine.web.template.authority.view.StaffVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * @Author: yls
 * @Date 2022/2/9 16:08
 * @Description: 数据权限隔离controller
 * @Version 1.0
 **/
@Slf4j
@RestController
@RequestMapping("component/staff")
@Api(tags = "组件模块-数据权限隔离测试")
public class StaffController {

    @Resource
    private IStaffFacade staffFacade;

    @Resource
    private IStaffService staffService;


    @SystemControllerLog(operation = LogConstant.READ)
    @ApiOperation("查询员工数据（3表联查）")
    @PostMapping("listStaffByPermission")
    public HttpResponseVO<List<StaffVO>> listStaffByPermission() {
        List<StaffVO> result = staffFacade.listStaffByPermission();
        return new HttpResponseVO<List<StaffVO>>().ok("", result);
    }

    @SystemControllerLog(operation = LogConstant.CREATE)
    @ApiOperation("添加员工数据(列权限)")
    @PostMapping("insertStaffByPermission")
    public HttpResponseVO<StaffDO> insertStaffByPermission(@RequestBody StaffDO staff) throws ServiceException {
        staffFacade.insertStaff(staff);
        return new HttpResponseVO<StaffDO>().ok("添加成功", staff);
    }

    @SystemControllerLog(operation = LogConstant.UPDATE)
    @ApiOperation("修改员工数据(列权限)")
    @PostMapping("updateStaffByPermission")
    public HttpResponseVO<StaffDO> updateStaffByPermission(@RequestBody StaffDO staff) throws ServiceException {
        staffFacade.updateStaff(staff);
        return new HttpResponseVO<StaffDO>().ok("", staff);
    }

    /**
     * // InterceptorIgnore()  // 数据拦截注解
     */
    @SystemControllerLog(operation = LogConstant.READ)
    @ApiOperation("查询员工数据（数据隔离：多线程）")
    @PostMapping("listStaffsThread")
    @DataPermissionFilter(mapper = StaffMapper.class, function = "staff:select")
    public HttpResponseVO<List<StaffDO>> listStaffsThread() {
        // 获取当前登录的用户信息
        UserDO user = SecurityUtils.getUser();
        Executor executor = Executors.newFixedThreadPool(2);
        List<StaffDO> result = new ArrayList<>();
        for (int i = 0; i < 1; i++) {
            executor.execute(() -> {
                // 在子线程中注入父级线程获取的当前登录用户信息，否则线程中无法获取用户数据
                DataFilterThreadLocal.setUser(user);
                staffService.listStaffsByThread();
                log.info("数据隔离模拟多线程:{}:{} ", Thread.currentThread().getName(), result);
            });
        }

        return new HttpResponseVO<List<StaffDO>>().ok("", result);
    }

    @SystemControllerLog(operation = LogConstant.READ)
    @ApiOperation("查询员工数据（数据隔离：多线程多表关联）")
    @PostMapping("listStaffsMoreThread")
    public HttpResponseVO<List<StaffDO>> listStaffsMoreThread() {
        // 获取当前登录的用户信息
        UserDO user = SecurityUtils.getUser();
        // 为了快捷测试，正式代码卜江义用Executors
        Executor executor = Executors.newFixedThreadPool(2);
        List<StaffDO> result = new ArrayList<>();
        int taskSize = 3;
        for (int i = 0; i < taskSize; i++) {
            executor.execute(() -> {
                // 在子线程中注入父级线程获取的当前登录用户信息，否则线程中无法获取用户数据
                List<StaffVO> staffs = staffFacade.listStaffByPermissionThread(user);
                log.info("数据隔离模拟多线程:{}:{} ", Thread.currentThread().getName(), staffs);
            });
        }

        return new HttpResponseVO<List<StaffDO>>().ok("", result);
    }


    @SystemControllerLog(operation = LogConstant.READ)
    @ApiOperation("查询员工数据（数据隔离：单线程）")
    @PostMapping("listStaffs")
    @DataPermissionFilter(function = "staff:select")
    public HttpResponseVO<List<StaffDO>> listStaffs() {
        List<StaffDO> result = staffService.listStaffs();
        return new HttpResponseVO<List<StaffDO>>().ok("", result);
    }

    @SystemControllerLog(operation = LogConstant.UPDATE)
    @ApiOperation("修改员工数据")
    @PostMapping("updateStaff")
    public HttpResponseVO<StaffDO> updateStaff(@RequestBody StaffDO staff) {
        staffService.updateStaff(staff);
        return new HttpResponseVO<StaffDO>().ok("", staff);
    }

    @SystemControllerLog(operation = LogConstant.READ)
    @ApiOperation("查询员工数据（未隔离）")
    @PostMapping("listStaffsNoDataPermission")
    public HttpResponseVO<List<StaffDO>> listStaffsNoDataPermission() {
        List<StaffDO> result = staffService.listStaffs();
        return new HttpResponseVO<List<StaffDO>>().ok("", result);
    }

    @SystemControllerLog(operation = LogConstant.CREATE)
    @ApiOperation("添加员工数据")
    @PostMapping("insertStaff")
    public HttpResponseVO<Object> insertStaff(@RequestBody StaffDO staff) {
        staffService.insertStaff(staff);
        return new HttpResponseVO<>().ok("添加成功");
    }

    @SystemControllerLog(operation = LogConstant.DELETE)
    @ApiOperation("删除所有员工数据")
    @PostMapping("deleteAllStaff")
    public HttpResponseVO<Object> deleteAllStaff() {
        staffService.deleteAllStaff();
        return new HttpResponseVO<>().ok("删除所有员工数据");
    }
}
